﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

using VirtualTournaments.DataAccess.SqlServer.DataMappers;

namespace VirtualTournaments.DataAccess.SqlServer.DataProxies
{
	internal class AllAgainstAllTournamentDataProxy : Business.Tournaments.AllAgainstAllTournament, ITournamentDataProxy, IDataProxy<SqlServer.Tournament>, Identifiable<SqlServer.Tournament>
	{
		internal AllAgainstAllTournamentDataProxy(SqlServer.Tournament dataObject, IEnumerable<Business.Tournaments.Team> teams)
			: base(teams)
		{
			InnerDataObject = dataObject;
			MapProperties();
		}

		#region Override properties

		internal bool FirstHasBeenRead { get; set; }
		public override Business.Tournaments.Team First
		{
			get
			{
				if (!FirstHasBeenRead)
				{
					FirstHasBeenRead = true;
					if (base.First == null)
					{
						base.First = MapFirst();
					}
				}
				return base.First;
			}
		}

		internal bool SecondHasBeenRead { get; set; }
		public override Business.Tournaments.Team Second
		{
			get
			{
				if (!SecondHasBeenRead)
				{
					SecondHasBeenRead = true;
					if (base.Second == null)
					{
						base.Second = MapSecond();
					}
				}
				return base.Second;
			}
		}

		internal bool ThirdHasBeenRead { get; set; }
		public override Business.Tournaments.Team Third
		{
			get
			{
				if (!ThirdHasBeenRead)
				{
					ThirdHasBeenRead = true;
					if (base.Third == null)
					{
						base.Third = MapThird();
					}
				}
				return base.Third;
			}
		}

		internal bool FixtureHasBeenRead { get; set; }
		public override Business.Tournaments.Fixture Fixture
		{
			get
			{
				if (!FixtureHasBeenRead)
				{
					FixtureHasBeenRead = true;
					if (base.Fixture == null)
					{
						base.Fixture = MapFixture();
					}
				}
				return base.Fixture;
			}
		}

		internal bool TeamsHasBeenRead { get; set; }
		public override IEnumerable<Business.Tournaments.Team> Teams
		{
			get
			{
				if (!TeamsHasBeenRead)
				{
					TeamsHasBeenRead = true;
					if (base.Teams == null)
					{
						base.Teams = MapTeams();
					}
				}
				return base.Teams;
			}
		}

		internal bool StandingsHasBeenRead { get; set; }
		public override Business.Tournaments.Standings Standings
		{
			get
			{
				if (!StandingsHasBeenRead)
				{
					StandingsHasBeenRead = true;
					if (base.Standings == null)
					{
						base.Standings = MapStandings();
					}
				}
				return base.Standings;
			}
		}

		#endregion

		#region Mapping methods

		private void MapProperties()
		{
			Name = InnerDataObject.Name;
			IsFinished = InnerDataObject.IsFinished;
			IsActive = InnerDataObject.IsActive;
			LastJourneyNumber = InnerDataObject.CurrentJourneyNumber;
		}

		private Business.Tournaments.Team MapFirst()
		{
			if (InnerDataObject.FirstTeam == null)
				return null;
			return TeamsDataMapper.Instance.DataObject2BusinessObject(InnerDataObject.FirstTeam);
		}

		private Business.Tournaments.Team MapSecond()
		{
			if (InnerDataObject.SecondTeam == null)
				return null;
			return TeamsDataMapper.Instance.DataObject2BusinessObject(InnerDataObject.SecondTeam);
		}

		private Business.Tournaments.Team MapThird()
		{
			if (InnerDataObject.ThirdTeam == null)
				return null;
			return TeamsDataMapper.Instance.DataObject2BusinessObject(InnerDataObject.ThirdTeam);
		}

		private IEnumerable<VirtualTournaments.Business.Tournaments.Team> MapTeams()
		{
			return InnerDataObject.TournamentTeams.Select(tournamentTeam => TeamsDataMapper.Instance.DataObject2BusinessObject(tournamentTeam.Team)).AsEnumerable();
		}

		private Business.Tournaments.Fixture MapFixture()
		{
			return new FixtureDataProxy(this, this);
		}

		private Business.Tournaments.Standings MapStandings()
		{
			return new StandingsDataProxy(this);
		}

		#endregion

		#region IDataProxy<Tournament> Members

		public SqlServer.Tournament InnerDataObject { get; set; }

		#endregion

		#region Identifiable<Tournament> Members

		public Expression<Func<SqlServer.Tournament, bool>> GetUniqueWhereExpression()
		{
			return tournament => tournament.TournamentId == InnerDataObject.TournamentId;
		}

		#endregion
	}
}
